package com.aspirecn.core.commons;

import java.io.File;
import java.io.IOException;
import java.net.URL;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.log4j.Logger;

/**
 * 文件操作通用方法
 * @author wangxinning
 *
 */
public class FileUtils extends org.apache.commons.io.FileUtils{

	public final static Logger logger = Logger.getLogger(FileUtils.class);
	public final static int SUCCESS = 1;
	public final static int TIME_SECOND = (int)DateUtils.MILLIS_PER_SECOND;
	public final static int TIME_MINUTE = TIME_SECOND * 60;

	/**
	 * 下载远程文件到本地
	 * 加入锁操作，确保文件完整下载
	 * 
	 * 返回值：
	 * -1:source=null
	 * -2:destination=null
	 * -3:已经有进程在下载该文件
	 * -4:锁文件建立失败
	 * -5:文件下载失败
	 * -6:备份源文件失败
	 * -7:临时文件转正失败
	 * -8:删除锁文件失败
	 * -9:文件内容没变
	 * 
	 * @param url
	 * @param file
	 * @return
	 */
	@SuppressWarnings("unused")
	public static int downloadRemoteFile( URL source, File destination, int connectionTimeout, int readTimeout ) 
	{
		logger.debug("source：" + source);
		logger.debug("destination：" + destination);
		
		long start = System.currentTimeMillis();
		
		int retCode = SUCCESS;
		long fileSize = 0;
		
		String extension = "lock";
		File lockFile = new File( destination.toString() + "." + extension );//定义锁文件
		extension = "tmp";
		File tempDestination = new File( destination.toString() + "." + extension );//下载中间文件
		
		//0.参数校验
		if( source == null && retCode == SUCCESS )
		{
			//URL为空
			retCode = -1;
		}
		else if( destination == null && retCode == SUCCESS )
		{
			//文件名为空
			retCode = -2;
		}
		
		//1.建立锁文件		
		//1.1锁文件存在并且建立时间小于一小时，说明正在下载，停止
		if( lockFile.exists() 
				&& System.currentTimeMillis()-lockFile.lastModified()<DateUtils.MILLIS_PER_HOUR 
				&& retCode == SUCCESS)
		{
			//锁文件存在，正在下载中......
			retCode = -3;
		}
		else if( retCode == SUCCESS )
		{
			//建立锁文件
			try
			{
				FileUtils.touch(lockFile);
				logger.debug("锁文件建立成功：" + lockFile);
			}
			catch( Exception e )
			{
				logger.error("锁文件建立失败" + lockFile, e);
				retCode = -4;
			}
		}
		
		//2.下载成临时文件		
		try
		{	
			if( retCode == SUCCESS )
			{
				if( tempDestination.exists() )
				{
					FileUtils.forceDelete(tempDestination);
				}
				FileUtils.copyURLToFile(
						source, 
						tempDestination, 
						connectionTimeout<= 0?TIME_MINUTE*2:connectionTimeout, 
						readTimeout <= 0?TIME_MINUTE*2:readTimeout
								);
				logger.debug("远程文件下载成功：" + source + " " + tempDestination);
				
				//更新最后下载时间戳文件
				extension = "stamp";
				File stampFile = new File( destination.toString() + "." + extension );//最后下载的时间文件
				FileUtils.write(stampFile, Long.toString(tempDestination.lastModified()), false);
				
				//内容相同，删除临时文件
				if (FileUtils.equals(destination, tempDestination)) {
					logger.error("下载文件与本地文件完全相同 tempDestination="
							+ tempDestination + ",destination=" + destination);
					retCode = -9;
					FileUtils.forceDelete(tempDestination);
				}
			}
		}
		catch( Exception e )
		{
			logger.error("文件下载失败" + source, e);
			retCode = -5;
		}
		
		//3.备份旧文件,只备份一次
		if( destination.exists() && retCode == SUCCESS )
		{
			extension = "bak";// + DateFormatUtils.format(new Date(), "MMddHHmm");
			File backupSrcDestination = new File( destination.toString() + "." + extension );
			try
			{
				if( backupSrcDestination.exists() )
				{
					FileUtils.forceDelete(backupSrcDestination);
				}
								
				FileUtils.moveFile(destination, backupSrcDestination);
				logger.debug("文件备份成功：" + destination + " " + backupSrcDestination);
			}
			catch( Exception e )
			{
				logger.error("备份源文件失败" + destination, e);
				retCode = -6;
			}
		}		
		
		try
		{
			if(retCode == SUCCESS)
			{
				FileUtils.moveFile(tempDestination, destination);
				fileSize = FileUtils.sizeOf(destination);
				logger.debug("文件move成功：" + tempDestination + " " + destination);
			}
		}
		catch( Exception e )
		{
			logger.error("临时文件转正失败" + destination, e);
			retCode = -7;
		}
		
		//4.删除锁文件，无论异常与否都要删除
		try
		{
			if( lockFile.exists() )
			{
				FileUtils.forceDelete(lockFile);
				logger.debug("锁文件删除成功：" + lockFile);
			}
		}
		catch( Exception e )
		{
			if(retCode == SUCCESS)
			{
				logger.error("删除锁文件失败" + lockFile, e);
				retCode = -8;
			}
		}
		
		//5.返回
		long end = System.currentTimeMillis();
		
		//6.构造日志
		String logstr = "文件下载结束，耗时：" + (end - start) + "ms!" + "url=" + source
				+ ",file=" + destination + ",size=";		
		long sizekb = fileSize
				/ FileUtils.ONE_KB;
		long sizemb = fileSize
				/ FileUtils.ONE_MB;
		if( sizemb > 0 )
		{
			logstr += sizemb + "MB";
		}
		else if( sizekb > 0 )
		{
			logstr += sizekb + "KB";
		}
		else
		{
			logstr += fileSize + "Byte";
		}
		
		logger.info(logstr);
		return retCode;
	}
	
	/**
	 * 判断两文件是否相同的简易方法
	 * @param file1
	 * @param file2
	 * @return
	 */
	public static boolean equals( File file1, File file2 )
	{
		// 一个是空一个不是
		if ((file1 == null && file2 != null)
				|| (file2 == null && file1 != null)) {
			return false;
		}

		// 存在不存在或者都不存在
		if ((file1.exists() && !file2.exists())
				|| (file2.exists() && !file1.exists())
				|| (!file1.exists() && !file2.exists())) {
			return false;
		}
		
		//crc32比较
		try
		{
			long file1CRC32 = FileUtils.checksumCRC32( file1 );
			long file2CRC32 = FileUtils.checksumCRC32( file2 );
			if( file1CRC32 != file2CRC32 )
			{
				return false;
			}
		}
		catch( Exception e )
		{
			logger.error("文件CRC32比对失败 " + file1 + "," + file2, e);
			return false;
		}	
		
		return true;
	}
	
	
	/**
	 * 获取文件最后下载时间，如果有时间戳文件，以此文件内容为准
	 * @param file
	 * @return
	 * @throws IOException 
	 */
	public static long getLastDownloadTime( File file )
	{
		String extension = "stamp";
		File stampFile = new File( file.toString() + "." + extension );//最后下载的时间文件
		
		long lastDownload = 0;//最后下载的时间点
		if( file.exists() )
		{
			lastDownload = file.lastModified();
			
			if( stampFile.exists() )
			{
				try {
					lastDownload = NumberUtils.toLong(StringUtils.trim(FileUtils.readFileToString(stampFile)));
				} catch (IOException e) {
					logger.error("读取时间戳文件异常",e);
				}
			}
		}
		
		
		return lastDownload;
	}

	
	
	public static void main( String[] args ) throws IOException
	{
		File f = new File("\\\\10.2.2.143\\new_release_storage\\WAP\\特殊版本_特殊PATCH\\NM-SHARE-COMMON V3.0.0\\cfg.i139.cn\\2013-09-27\\common\\uaV3.zip");
		System.out.println( FileUtils.checksumCRC32(f) );
		
		
		//ZipUtil.unZipFile("F:\\xmlua.zip", "F:\\", 1);
		
//		String url = "http://cfg.api.i139.cn/common/xss/xss.txt";
//		
//		File f1 = new File("D:/xss.txt");
//		//File f2 = new File("D:/ua.json.bak07031031");
//		downloadRemoteFile( new URL(url), f1, 0,0 );
		
//		System.out.println( org.apache.commons.io.FileUtils.sizeOf(f1) );
//		System.out.println( org.apache.commons.io.FileUtils.sizeOf(f2) );
//		
//		//long l1 = 
//		System.out.println( org.apache.commons.io.FileUtils.contentEquals(f1, f2) );
//		System.out.println( org.apache.commons.io.FileUtils.checksumCRC32(f2) );
	}
}